package org.delphy.indy2.containers
{	
	import flash.display.*;
	import flash.events.*;
	import flash.utils.*;
	
	import mx.containers.Canvas;
	import mx.controls.Image;
	import mx.controls.Alert;
	
	public class CarbonVineGenerator extends Canvas
	{

		//--------------------------------------
		//  Animation and positioning
		//--------------------------------------

		/**
		 * @public
		 * 
		 * @default 0
		 */
		public var startX:Number=0;
		
		/**
		 * @public
		 * 
		 * @default 0
		 */
		public var startY:Number=0;
		
		/**
		 * @public
		 * 
		 * @default 3
		 */
		public var recursionLevel:Number=3;
		
		/**
		 * @public
		 * 
		 * @default 0.01
		 */
		public var speed:Number=0.01;
		
		/**
		 * @public
		 * 
		 * @default 1000
		 */
		public var maxOperationsPerIteration:Number=1000;

		/**
		 * @protected
		 */
		protected var timer:Timer;

		//--------------------------------------
		//  Bitmaps
		//--------------------------------------

		/**
		 * @public
		 */
		public var source:Object;
		
		/**
		 * @protected
		 */
		protected var sourceImage:Image;
		
		/**
		 * @protected
		 */
		protected var bmp:BitmapData;

		/**
		 * @protected
		 */
		protected var destBmp:BitmapData;

		/**
		 * @protected
		 */
		protected var destBitmap:Bitmap;
		
		/**
		 * @public
		 */
		public var maskColor:Number=-1;
		
		/**
		 * @protected
		 */
		protected var pixelArray:Array = [];		
		
		/**
		 * Constructor
		 */
		public function CarbonVineGenerator()
		{
			super();
		}

		/**
		 * @public
		 */
		public function generate():void
		{
			sourceImage = new Image();
			sourceImage.width=width;
			sourceImage.height=height;
			sourceImage.source=source;
			sourceImage.visible=false;
			addChild(sourceImage);
			
			bmp= new BitmapData(width,height,true,0x00000000);
			bmp.draw(sourceImage);
			
			if(maskColor==-1)
				maskColor=bmp.getPixel32(1,1);
				
			if (maskColor==bmp.getPixel32(startX,startY))
			{
				trace("CarbonVineGenerator: Bad start point");
				return;
			}

			destBmp = new BitmapData(width,height,true,0x00000000);
			destBitmap=new Bitmap(destBmp);
			rawChildren.addChild(destBitmap);
			
			bitTrace(startX,startY,0);
			
			timer=new Timer(speed*1000);
			timer.addEventListener(TimerEvent.TIMER,process);
			timer.start();			
		}
		
		/**
		 * @public
		 */
		public function process(evt:Event=null):void
		{
			var count:Number=pixelArray.length;
			
			if (count==0)
			{
				timer.stop();
				rawChildren.removeChild(sourceImage);
				for (var i:uint=0; i < width; i++)
				{
					for (var j:int = 0; j < height; j++)
					{
						var c:Number = bmp.getPixel32(i,j);
						if (c!=maskColor)
						{
							destBmp.setPixel32(i,j,c);
						}
					}
				}
			}
			
			
			for (i=0; i < count && i<maxOperationsPerIteration; i++)
			{
				var pix:Object=pixelArray.shift();
				bitTrace(pix.x,pix.y,0);
			}
			
		}
		
		/**
		 * @public
		 */
		public function bitTrace(x:Number,y:Number,level:Number):void
		{
			if (destBmp.getPixel(x,y)!=0x000000)
			{
				return;
			}
			if (level++ > recursionLevel)
			{
				var pix:Object={x:x,y:y};
				pixelArray.push(pix);
				return;
			}
			
			destBmp.setPixel32(x,y,bmp.getPixel32(x,y));
			
			var tArray:Array=new Array({index:1,x:x-1,y:y-1}, {index:2,x:x,y:y-1},
									   {index:3,x:x+1,y:y-1}, {index:4,x:x+1,y:y}, 
									   {index:5,x:x+1,y:y+1}, {index:6,x:x,y:y+1}, 
									   {index:7,x:x-1,y:y+1}, {index:8,x:x,y:y-1} );
									   
			while (tArray.length>0)
			{
				var x1:Number=tArray[0].x;
				var y1:Number=tArray[0].y;
				var index:Number=tArray[0].index;
				var c2:Number=destBmp.getPixel32(x1,y1);
				
				if (c2==0x00000000)
				{
					var c:Number=bmp.getPixel32(x1,y1);
					
					if (c!=0 && c!=maskColor)
					{
						bitTrace(x1,y1,level);
						
						if(tArray.length!=1){
							if (tArray[1].index == index+1)
							{
								tArray.shift();
							}
							if (tArray[tArray.length-1].index % 8 == index-1)
							{
								tArray.pop();
							}
						}
					}
				}
				
				tArray.shift();
				
			}
		}

	}
}